這幾天均會說明TF的資料處理。雖然資料處理真的非常瑣碎也煩人,常常會處理到起瘋。但資料處理對一個ML project或者Data science project非常重要。俗話說的好 "Garbage in , Garbage out !",所以真的要很小心注意資料處理的步驟,有時候Model train壞,只是因為資料處理的步驟出了問題,而資料處理就會佔掉您60% ~ 70%的時間。因此,若您可以熟悉這些語法,或許可以加速您在資料處理的步驟。
一般來說,以一個影像辨識的data shape,我們會將資料擺成 [batch, height(row), width(columns),channel] 。Ex: [128,64,64,1]。因次第一個說明的就是最常看到的reshape
常常我們可能想資料轉換樣式,或者是把shape轉成我們想要的樣式 Ex: [64,32,32] -> [64, 32*32],將想是將一個image[b,h,w,3] 轉成 [b,pixcel,3]。類似將一個2維度的Matrix轉成一個1維度的array。
#Create samples
a = tf.random.normal([6,32,32,3])
#Reshape to different type
tf.reshape(a,[6,32*32,3]).shape
#Output:TensorShape([6, 1024, 3])
tf.reshape(a,[6,-1,3]).shape
#Output:TensorShape([6, 1024, 3])
[註]: 將reshape中的欄位設為-1,他會自動計算
或者也可以一次使用兩次reshape來轉換資料。例如:
tf.reshape(tf.reshape(a,[6,-1]),[6,16,-1,3]).shape
#Output:TensorShape([6, 16, 64, 3])
如果要將資料轉回來,Ex: [6,1024,3] -> [6,32,32,3]。要保留原有shpae的資訊就可以轉回來。
當你想要將matrix的欄位對調,Ex; [6,32,32,3] -> [6,32,3,32],就可以使用transpose來對調。有時候我們會將[b,h,w,3] -> [b,3,h,w] (Pytorch格式),就可以使用tf.transpose來轉。
tf.transpose(a,perm=[0,1,3,2]).shape
#Output:TensorShape([6, 32, 3, 32])
當如果您想到增加一個維度,例如原本你有一個 [32,32,3]的圖,但您想新增新的一維度來記錄他的資料量,或者一個batch的量。就可以使用tf.expamd_dims來新增。
a = tf.random.normal([32,32,3])
tf.expand_dims(a,axis=0).shape
#Output:TensorShape([1,32,32,3])
Broadcast的function就是broadcast數值,但實際上,儲存或者variable size都是沒有變化,不會去複製data。因此,在儲存效率上,是有較好的。簡單的案例就像是我們在做Linear regression的時候,在 X*W+b的時候,通常b會以broadcast的方式來執行 (之後會有實作Linear regression)。
(註: broadcast的時候,要對齊最右邊的那個維度,若非1,則必須相等)
x = tf.random.normal([4,40,12])
(x + tf.random.normal([40,1])).shape
#Output:TensorShape([4, 40, 12])
(註1: 因為broadcast是一種內建的優化方式,TF會自斷判斷是否可以broadcast,不用特別寫broadcast)
(註2:假如你想broadcast且b的維度變成broadcast 後的相同維度,可以參考tf.broadcast_to 以及tf.tile)
假如我今天有兩個資料,想要以row wise的方式合併在一起,Ex: (#row,#cols) A[6,12] + B[6,12] = [12,12]。此時,可以使用tf.concat來合併資料。
a = tf.ones([6,32,3])
b = tf.ones([6,32,3])
tf.concat([a,b],axis=0).shape
#Output:TensorShape([12, 32, 3])
此外,可以透過axis來調控你要合併by哪一個axis
a = tf.ones([6,32,3])
b = tf.ones([6,32,3])
tf.concat([a,b],axis=1).shape
#Output:TensorShape([6, 64, 3])
假如我今天有兩個資料,想要以column wise的方式合併在一起,類似新增一個column,Ex: (#row,#cols) A[6,12] + B[6,12] = [2,6,12]。此時,可以使用tf.stack來合併資料。
a = tf.ones([6,32,3])
b = tf.ones([6,32,3])
tf.stack([a,b],axis=0).shape
#Output:TensorShape([2,6, 64, 3])
Split的話,這邊會比較unstack跟split的用法
unstack與stack正好相反,也就是拿掉Column
a = tf.ones([2,32,3])
aa,ab= tf.unstack(a,axis=0)
aa.shape
#Output:TensorShape([32, 3])
data_all = tf.unstack(a,axis=1)
data_all[0].shape
#Output:TensorShape([2, 3])
len(data_all)
#Output:32
split的話就會比較直觀,就是直接針對指定Column然後切幾分這樣。
data_all = tf.split(a,axis=1,num_or_size_splits=2)
data_all[0].shape
#Output:TensorShape([2, 16, 3])
len(data_all)
#Output:2
小結:
這次是簡易的一些TF的資料處理的語法,資料處理真的很繁雜,真的需要耐性將資料處理乾淨,且確認沒有問題才能將資料放入模型。大家可以玩玩看,並且我下面連結我會放上是示範的Colab[註1]。若有任何問題大家可以討論交流,感謝您的閱讀。
一日一梗圖: